home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / math / ast51src.zip / CHARTS2.C < prev    next >
C/C++ Source or Header  |  1995-12-31  |  31KB  |  905 lines

  1. /*
  2. ** Astrolog (Version 5.10) File: charts2.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1995 by Walter D. Pullen
  6. ** (Astara@msn.com). Permission is granted to freely use and
  7. ** distribute these routines provided one doesn't sell, restrict, or
  8. ** profit from them in any way. Modification is allowed provided these
  9. ** notices remain with any altered or edited versions of the program.
  10. **
  11. ** The main planetary calculation routines used in this program have
  12. ** been Copyrighted and the core of this program is basically a
  13. ** conversion to C of the routines created by James Neely as listed in
  14. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  15. ** available from Matrix Software. The copyright gives us permission to
  16. ** use the routines for personal use but not to sell them or profit from
  17. ** them in any way.
  18. **
  19. ** The PostScript code within the core graphics routines are programmed
  20. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  21. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  22. **
  23. ** The extended accurate ephemeris databases and formulas are from the
  24. ** calculation routines in the program "Placalc" and are programmed and
  25. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  26. ** (alois@azur.ch). The use of that source code is subject to
  27. ** regulations made by Astrodienst Zurich, and the code is not in the
  28. ** public domain. This copyright notice must not be changed or removed
  29. ** by any user of this program.
  30. **
  31. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  32. ** X Window graphics initially programmed 10/23-29/1991.
  33. ** PostScript graphics initially programmed 11/29-30/1992.
  34. ** Last code change made 12/27/1995.
  35. */
  36.  
  37. #include "astrolog.h"
  38.  
  39.  
  40. /*
  41. ******************************************************************************
  42. ** Dual Chart Display Routines.
  43. ******************************************************************************
  44. */
  45.  
  46. /* Print out an aspect (or midpoint if -g0 switch in effect) grid of a      */
  47. /* relationship chart. This is similar to the ChartGrid() routine; however, */
  48. /* here we have both axes labeled with the planets for the two charts in    */
  49. /* question, instead of just a diagonal down the center for only one chart. */
  50.  
  51. void ChartGridRelation()
  52. {
  53.   char sz[cchSzDef];
  54.   int i, j, k, tot = cObj, temp;
  55.  
  56. #ifdef INTERPRET
  57.   if (us.fInterpret && !us.fGridConfig) {
  58.     InterpretGridRelation();
  59.     return;
  60.   }
  61. #endif
  62.   PrintSz(" 2>");
  63.   for (temp = 0, i = 1; i <= cObj; i++) if (!ignore[i]) {
  64.     PrintCh(chV);
  65.     AnsiColor(kObjA[i]);
  66.     sprintf(sz, "%c%c%c", chObj3(i)); PrintSz(sz);
  67.     AnsiColor(kDefault);
  68.     temp++;
  69.   }
  70.   PrintSz("\n1  ");
  71.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  72.     PrintCh(chV);
  73.     AnsiColor(kSignA(SFromZ(cp2.obj[i])));
  74.     sprintf(sz, "%2d%c", (int)cp2.obj[i] % 30, chDeg0); PrintSz(sz);
  75.     AnsiColor(kDefault);
  76.   }
  77.   PrintSz("\nV  ");
  78.   for (i = 1; i <= tot; i++) if (!ignore[i]) {
  79.     PrintCh(chV);
  80.     temp = SFromZ(cp2.obj[i]);
  81.     AnsiColor(kSignA(temp));
  82.     sprintf(sz, "%c%c%c", chSig3(temp)); PrintSz(sz);
  83.     AnsiColor(kDefault);
  84.   }
  85.   PrintL();
  86.   for (j = 1; j <= cObj; j++) if (!ignore[j])
  87.     for (k = 1; k <= 4; k++) {
  88.       if (k < 2)
  89.         PrintTab(chH, 3);
  90.       else if (k == 2) {
  91.         AnsiColor(kObjA[j]);
  92.         sprintf(sz, "%c%c%c", chObj3(j)); PrintSz(sz);
  93.       } else {
  94.         temp = SFromZ(cp1.obj[j]);
  95.         AnsiColor(kSignA(temp));
  96.         if (k == 3)
  97.           sprintf(sz, "%2d%c", (int)cp1.obj[j] - (temp-1)*30, chDeg0);
  98.         else
  99.           sprintf(sz, "%c%c%c", chSig3(temp));
  100.         PrintSz(sz);
  101.       }
  102.       if (k > 1)
  103.         AnsiColor(kDefault);
  104.       for (i = 1; i <= tot; i++) if (!ignore[i]) {
  105.         PrintCh((char)(k < 2 ? chC : chV));
  106.         temp = grid->n[i][j];
  107.         if (k > 1) {
  108.           if (i == j)
  109.             AnsiColor(kReverse);
  110.           AnsiColor(us.fGridConfig ? kSignA(temp) :
  111.             kAspA[temp]);
  112.         }
  113.         if (k < 2)
  114.           PrintTab(chH, 3);
  115.         else if (k == 2) {
  116.           if (us.fGridConfig)
  117.             sprintf(sz, "%c%c%c", chSig3(temp));
  118.           else
  119.             sprintf(sz, "%s", temp ? szAspectAbbrev[temp] : "   ");
  120.           PrintSz(sz);
  121.         } else if (k == 3) {
  122.           if (us.fGridConfig) {
  123.             sprintf(sz, "%2d%c", grid->v[i][j]/60, chDeg0); PrintSz(sz);
  124.           } else
  125.             if (grid->n[i][j]) {
  126.               if (grid->v[i][j] < 6000)
  127.                 sprintf(sz, "%c%2d", us.fAppSep ?
  128.                   (grid->v[i][j] < 0 ? 'a' : 's') :
  129.                   (grid->v[i][j] < 0 ? '-' : '+'), abs(grid->v[i][j])/60);
  130.               else
  131.                 sprintf(sz, "%3d", abs(temp)/60);
  132.               PrintSz(sz);
  133.             } else
  134.               PrintSz("   ");
  135.         } else {
  136.           if (grid->n[i][j]) {
  137.             sprintf(sz, "%02d'", abs(grid->v[i][j])%60); PrintSz(sz);
  138.           } else
  139.             PrintSz("   ");
  140.         }
  141.         AnsiColor(kDefault);
  142.       }
  143.       PrintL();
  144.     }
  145. }
  146.  
  147.  
  148. /* Display all aspects between objects in the relationship comparison chart, */
  149. /* one per line, in sorted order based on the total "power" of the aspects,  */
  150. /* as specified with the -r0 -a switch combination.                          */
  151.  
  152. void ChartAspectRelation()
  153. {
  154.   char sz[cchSzDef];
  155.   int pcut = 30000, icut, jcut, phi, ihi, jhi, ahi, p, i, j, k, count = 0;
  156.   real ip, jp;
  157.  
  158.   loop {
  159.     phi = -1;
  160.  
  161.     /* Search for the next most powerful aspect in the aspect grid. */
  162.  
  163.     for (i = 1; i <= cObj; i++) if (!ignore[i])
  164.       for (j = 1; j <= cObj; j++) if (!ignore[j])
  165.         if (k = grid->n[i][j]) {
  166.           ip = i <= oNorm ? rObjInf[i] : 2.5;
  167.           jp = j <= oNorm ? rObjInf[j] : 2.5;
  168.           p = (int)(rAspInf[k]*(ip+jp)/2.0*
  169.             (1.0-RAbs((real)(grid->v[i][j]))/60.0/rAspOrb[k])*1000.0);
  170.           if ((p < pcut || (p == pcut && (i > icut ||
  171.             (i == icut && j > jcut)))) && p > phi) {
  172.             ihi = i; jhi = j; phi = p; ahi = k;
  173.           }
  174.         }
  175.     if (phi < 0)    /* Exit when no less powerful aspect found. */
  176.       break;
  177.     pcut = phi; icut = ihi; jcut = jhi;
  178.     count++;                              /* Display the current aspect.   */
  179. #ifdef INTERPRET
  180.     if (us.fInterpret) {                  /* Interpret it if -I in effect. */
  181.       InterpretAspectRelation(jhi, ihi);
  182.       continue;
  183.     }
  184. #endif
  185.     sprintf(sz, "%3d: ", count); PrintSz(sz);
  186.     PrintAspect(jhi, SFromZ(cp1.obj[jhi]), (int)RSgn(cp1.dir[jhi]), ahi,
  187.       ihi, SFromZ(cp2.obj[ihi]), (int)RSgn(cp2.dir[ihi]), 'A');
  188.     k = grid->v[ihi][jhi];
  189.     AnsiColor(k < 0 ? kWhite : kLtGray);
  190.     sprintf(sz, "- orb: %c%d,%02d'",
  191.       us.fAppSep ? (k < 0 ? 'a' : 's') : (k < 0 ? '-' : '+'),
  192.       abs(k)/60, abs(k)%60); PrintSz(sz);
  193.     AnsiColor(kDkGreen);
  194.     sprintf(sz, " - power:%6.2f\n", (real)phi/1000.0); PrintSz(sz);
  195.     AnsiColor(kDefault);
  196.   }
  197. }
  198.  
  199.  
  200. /* Display locations of all midpoints between objects in the relationship */
  201. /* comparison chart, one per line, in sorted zodiac order from zero Aries */
  202. /* onward, as specified with the -r0 -m switch combination.               */
  203.  
  204. void ChartMidpointRelation()
  205. {
  206.   char sz[cchSzDef];
  207.   int mcut = -1, icut, jcut, mlo, ilo, jlo, m, i, j, count = 0;
  208.  
  209.   loop {
  210.     mlo = 21600;
  211.  
  212.     /* Search for the next closest midpoint farther down in the zodiac. */
  213.  
  214.     for (i = 1; i <= cObj; i++) if (!ignore[i])
  215.       for (j = 1; j <= cObj; j++) if (!ignore[j]) {
  216.         m = (grid->n[j][i]-1)*30*60 + grid->v[j][i];
  217.         if ((m > mcut || (m == mcut && (i > icut ||
  218.           (i == icut && j > jcut)))) && m < mlo) {
  219.           ilo = i; jlo = j; mlo = m;
  220.         }
  221.       }
  222.     if (mlo >= 21600)    /* Exit when no midpoint farther in zodiac found. */
  223.       break;
  224.     mcut = mlo; icut = ilo; jcut = jlo;
  225.     count++;                               /* Display the current midpoint. */
  226. #ifdef INTERPRET
  227.     if (us.fInterpret) {                   /* Interpret it if -I in effect. */
  228.       InterpretMidpointRelation(ilo, jlo);
  229.       continue;
  230.     }
  231. #endif
  232.     sprintf(sz, "%4d: ", count); PrintSz(sz);
  233.     PrintZodiac((real)mlo/60.0);
  234.     PrintCh(' ');
  235.     PrintAspect(ilo, SFromZ(cp1.obj[ilo]), (int)RSgn(cp1.dir[ilo]), 0,
  236.       jlo, SFromZ(cp2.obj[jlo]), (int)RSgn(cp2.dir[jlo]), 'M');
  237.     AnsiColor(kDefault);
  238.     m = (int)(MinDistance(cp1.obj[ilo], cp2.obj[jlo])*60.0);
  239.     sprintf(sz, "-%4d%c%02d' degree span.\n", m/60, chDeg1, m%60);
  240.     PrintSz(sz);
  241.   }
  242. }
  243.  
  244.  
  245. /* Calculate any of the various kinds of relationship charts. This involves */
  246. /* reading in and storing the planet and house positions for both charts,   */
  247. /* and then combining them in the main single chart in the proper manner.   */
  248. /* If the parameter 'fFile' is on, then we read the info for the two charts */
  249. /* from files, otherwise use the info in preset "core" and "second" charts. */
  250.  
  251. void CastRelation(fFile)
  252. bool fFile;
  253. {
  254.   byte ignoreT[objMax];
  255.   CI ciT;
  256.   int i;
  257.   real ratio, t1, t2, t;
  258.  
  259.   /* Read in and cast the first chart. */
  260.  
  261. #ifdef WIN
  262.   if (is.szFile == NULL || is.szFile2 == NULL)
  263.     fFile = fFalse;
  264. #endif
  265.   if (fFile)
  266.     FInputData(is.szFile);
  267.   ciT = ciCore;
  268.   if (fFile)
  269.     ciTwin = ciCore;
  270.   else
  271.     ciCore = ciTwin;
  272.   t1 = CastChart(fTrue);
  273.   for (i = 1; i <= cSign; i++) {
  274.     cp1.cusp[i] = house[i];
  275.     cp1.house[i] = inhouse[i];
  276.   }
  277.   for (i = 1; i <= cObj; i++) {
  278.     cp1.obj[i] = planet[i];
  279.     cp1.alt[i] = planetalt[i];
  280.     cp1.dir[i] = ret[i];
  281.   }
  282.  
  283.   /* Read in the second chart. */
  284.  
  285.   if (fFile) {
  286.     FInputData(is.szFile2);
  287.     if (us.nRel == rcProgress) {
  288.       us.fProgress = fTrue;
  289.       is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  290.       ciCore = ciT;
  291.     }
  292.   } else
  293.     ciCore = ciT;
  294.   ciMain = ciCore;
  295.   if (us.nRel == rcTransit)
  296.     for (i = 1; i <= cObj; i++) {
  297.       ignoreT[i] = ignore[i];
  298.       ignore[i] = ignore[i] && ignore2[i];
  299.     }
  300.   t2 = CastChart(fTrue);
  301.   if (us.nRel == rcTransit)
  302.     for (i = 1; i <= cObj; i++)
  303.       ignore[i] = ignoreT[i];
  304.   for (i = 1; i <= cSign; i++) {
  305.     cp2.cusp[i] = house[i];
  306.     cp2.house[i] = inhouse[i];
  307.   }
  308.   for (i = 1; i <= cObj; i++) {
  309.     cp2.obj[i] = planet[i];
  310.     cp2.alt[i] = planetalt[i];
  311.     cp2.dir[i] = ret[i];
  312.   }
  313.  
  314.   /* Now combine the two charts based on what relation we are doing.   */
  315.   /* For the standard -r synastry chart, use the house cusps of chart1 */
  316.   /* and the planets positions of chart2.                              */
  317.  
  318.   ratio = (real)us.nRatio1 / ((real)(us.nRatio1 + us.nRatio2));
  319.   if (us.nRel <= rcSynastry)
  320.     for (i = 1; i <= cSign; i++)
  321.       house[i] = cp1.cusp[i];
  322.  
  323.   /* For the -rc composite chart, take the midpoints of the planets/houses. */
  324.  
  325.   else if (us.nRel == rcComposite) {
  326.     for (i = 1; i <= cObj; i++) {
  327.       planet[i] = Ratio(cp1.obj[i], cp2.obj[i], ratio);
  328.       if (RAbs(cp2.obj[i] - cp1.obj[i]) > rDegHalf)
  329.         planet[i] = Mod(planet[i] + rDegMax*ratio);
  330.       planetalt[i] = Ratio(cp1.alt[i], cp2.alt[i], ratio);
  331.       ret[i] = Ratio(cp1.dir[i], cp2.dir[i], ratio);
  332.     }
  333.     for (i = 1; i <= cSign; i++) {
  334.       house[i] = Ratio(cp1.cusp[i], cp2.cusp[i], ratio);
  335.       if (RAbs(cp2.cusp[i] - cp1.cusp[i]) > rDegHalf)
  336.         house[i] = Mod(house[i] + rDegMax*ratio);
  337.     }
  338.  
  339.     /* Make sure we don't have any 180 degree errors in house cusp    */
  340.     /* complement pairs, which may happen if the cusps are far apart. */
  341.  
  342.     for (i = 1; i <= cSign; i++)
  343.       if (MinDistance(house[sCap], Mod(house[i]-ZFromS(i+3))) > rDegQuad)
  344.         house[i] = Mod(house[i]+rDegHalf);
  345.     for (i = 1; i <= cSign; i++)
  346.       if (RAbs(MinDistance(house[i], planet[oAsc - 1 + i])) > rDegQuad)
  347.         planet[oAsc - 1 + i] = Mod(planet[oAsc - 1 + i]+rDegHalf);
  348.  
  349.   /* For the -rm time space midpoint chart, calculate the midpoint time and */
  350.   /* place between the two charts and then recast for the new chart info.   */
  351.  
  352.   } else if (us.nRel == rcMidpoint) {
  353.     T = Ratio(t1, t2, ratio);
  354.     t = (T*36525.0)+rRound; is.JD = RFloor(t)+2415020.0; TT = RFract(t)*24.0;
  355.     ZZ = Ratio(DecToDeg(ciT.zon), DecToDeg(Zon), ratio);
  356.     SS = Ratio(DecToDeg(ciT.dst), DecToDeg(Dst), ratio);
  357.     TT -= ZZ - SS;
  358.     if (TT < 0.0) {
  359.       TT += 24.0; is.JD -= 1.0;
  360.     }
  361.     JulianToMdy(is.JD, &MM, &DD, &YY);
  362.     OO = Ratio(DecToDeg(ciT.lon), DecToDeg(Lon), ratio);
  363.     if (RAbs(Lon-ciT.lon) > rDegHalf)
  364.       OO = Mod(OO+rDegMax*ratio);
  365.     AA = Ratio(DecToDeg(ciT.lat), DecToDeg(Lat), ratio);
  366.     TT = DegToDec(TT); SS = DegToDec(SS); ZZ = DegToDec(ZZ);
  367.     OO = DegToDec(OO); AA = DegToDec(AA);
  368.     ciMain = ciCore;
  369.     CastChart(fTrue);
  370.  
  371.   /* There are a couple of non-astrological charts, which only require the */
  372.   /* number of days that have passed between the two charts to be done.    */
  373.  
  374.   } else
  375.     is.JD = RAbs(t2-t1)*36525.0;
  376.   ComputeInHouses();
  377.   if (us.nRel == rcProgress)
  378.     us.fProgress = fFalse;
  379. }
  380.  
  381.  
  382. /*
  383. ******************************************************************************
  384. ** Other Chart Display Routines.
  385. ******************************************************************************
  386. */
  387.  
  388. /* Given two objects and an aspect between them, or an object and a sign  */
  389. /* that it's entering, print if this is a "major" event, such as a season */
  390. /* change or major lunar phase. This is called from the ChartInDay()      */
  391. /* searching and influence routines. Do an interpretation if need be too. */
  392.  
  393. void PrintInDay(source, aspect, dest)
  394. int source, aspect, dest;
  395. {
  396.   if (aspect == aSig) {
  397.     if (source == oSun) {
  398.       AnsiColor(kWhite);
  399.       if (dest == 1)
  400.         PrintSz(" (Vernal Equinox)");     /* If the Sun changes sign, */
  401.       else if (dest == 4)                 /* then print out if this   */
  402.         PrintSz(" (Summer Solstice)");    /* is a season change.      */
  403.       else if (dest == 7)
  404.         PrintSz(" (Autumnal Equinox)");
  405.       else if (dest == 10)
  406.         PrintSz(" (Winter Solstice)");
  407.     }
  408.   } else if (aspect > 0) {
  409.     if (source == oSun && dest == oMoo) {
  410.       if (aspect <= aSqu)
  411.         AnsiColor(kWhite);
  412.       if (aspect == aCon)
  413.         PrintSz(" (New Moon)");     /* Print out if the present */
  414.       else if (aspect == aOpp)      /* aspect is a New, Full,   */
  415.         PrintSz(" (Full Moon)");    /* or Half Moon.            */
  416.       else if (aspect == aSqu)
  417.         PrintSz(" (Half Moon)");
  418.     }
  419.   }
  420.   PrintL();
  421.  
  422. #ifdef INTERPRET
  423.   if (us.fInterpret)
  424.     InterpretInDay(source, aspect, dest);
  425. #endif
  426.   AnsiColor(kDefault);
  427. }
  428.  
  429.  
  430. /* Given two objects and an aspect (or one object, and an event such as a */
  431. /* sign or direction change) display the configuration in question. This  */
  432. /* is called by the many charts which list aspects among items, such as   */
  433. /* the -a aspect lists, -m midpoint lists, -d aspect in day search and    */
  434. /* influence charts, and -t transit search and influence charts.          */
  435.  
  436. void PrintAspect(obj1, sign1, ret1, asp, obj2, sign2, ret2, chart)
  437. int obj1, sign1, ret1, asp, obj2, sign2, ret2;
  438. char chart;
  439. {
  440.   char sz[cchSzDef];
  441.  
  442.   AnsiColor(kObjA[obj1]);
  443.   if (chart == 't' || chart == 'T')
  444.     PrintSz("trans ");
  445.   else if (chart == 'e' || chart == 'u' || chart == 'U')
  446.     PrintSz("progr ");
  447.   sprintf(sz, "%7.7s", szObjName[obj1]); PrintSz(sz);
  448.   AnsiColor(kSignA(sign1));
  449.   sprintf(sz, " %c%c%c%c%c",
  450.     ret1 > 0 ? '(' : (ret1 < 0 ? '[' : '<'), chSig3(sign1),
  451.     ret1 > 0 ? ')' : (ret1 < 0 ? ']' : '>')); PrintSz(sz);
  452.   AnsiColor(asp > 0 ? kAspA[asp] : kWhite);
  453.   PrintCh(' ');
  454.   if (asp == aSig)
  455.     sprintf(sz, "-->");                        /* Print a sign change. */
  456.   else if (asp == aDir)
  457.     sprintf(sz, "S/%c", obj2 ? chRet : 'D');   /* Print a direction change. */
  458.   else if (asp == 0)
  459.     sprintf(sz, chart == 'm' ? "&" : "with");
  460.   else
  461.     sprintf(sz, "%s", szAspectAbbrev[asp]);    /* Print an aspect. */
  462.   PrintSz(sz);
  463.   if (asp != aDir)
  464.     PrintCh(' ');
  465.   if (chart == 'A')
  466.     PrintSz("with ");
  467.   if (asp == aSig) {
  468.     AnsiColor(kSignA(obj2));
  469.     sprintf(sz, "%s", szSignName[obj2]); PrintSz(sz);
  470.   } else if (asp >= 0) {
  471.     AnsiColor(kSignA(sign2));
  472.     if (chart == 't' || chart == 'u' || chart == 'T' || chart == 'U')
  473.       PrintSz("natal ");
  474.     sprintf(sz, "%c%c%c%c%c ",
  475.       ret2 > 0 ? '(' : (ret2 < 0 ? '[' : '<'), chSig3(sign2),
  476.       ret2 > 0 ? ')' : (ret2 < 0 ? ']' : '>')); PrintSz(sz);
  477.     AnsiColor(kObjA[obj2]);
  478.     sprintf(sz, "%.10s", szObjName[obj2]); PrintSz(sz);
  479.   }
  480.   if (chart == 'D' || chart == 'T' || chart == 'U' ||
  481.     chart == 'a' || chart == 'A' || chart == 'm' || chart == 'M')
  482.     PrintTab(' ', 10-CchSz(szObjName[obj2]));
  483. }
  484.  
  485.  
  486. /* Based on the given chart information, display all the aspects taking   */
  487. /* place in the chart, as specified with the -D switch. The aspects are   */
  488. /* printed in order of influence determined by treating them as happening */
  489. /* outside among transiting planets, such that rare outer planet aspects  */
  490. /* are given more power than common ones among inner planets. (This is    */
  491. /* almost identical to the -a list, except the influences are different.) */
  492.  
  493. void ChartInDayInfluence()
  494. {
  495.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  496.   real power[MAXINDAY];
  497.   char sz[cchSzDef];
  498.   int occurcount = 0, i, j, k, l, m;
  499.  
  500.   /* Go compute the aspects in the chart. */
  501.  
  502.   i = us.fAppSep;
  503.   us.fAppSep = fTrue;     /* We always want applying vs. separating orbs. */
  504.   FCreateGrid(fFalse);
  505.   us.fAppSep = i;
  506.  
  507.   /* Search through the grid and build up the list of aspects. */
  508.  
  509.   for (j = 2; j <= cObj; j++) {
  510.     if (ignore[j])
  511.       continue;
  512.     for (i = 1; i < j; i++) {
  513.       if (ignore[i] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  514.         continue;
  515.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  516.       l = grid->v[i][j];
  517.       power[occurcount] =
  518.         ((i <= oNorm ? rTransitInf[i] : 2.0)/4.0)*
  519.         ((j <= oNorm ? rTransitInf[j] : 2.0)/4.0)*
  520.         rAspInf[k]*(1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  521.       occurcount++;
  522.     }
  523.   }
  524.  
  525.   /* Sort aspects by order of influence. */
  526.  
  527.   for (i = 1; i < occurcount; i++) {
  528.     j = i-1;
  529.     while (j >= 0 && power[j] < power[j+1]) {
  530.       SwapN(source[j], source[j+1]);
  531.       SwapN(aspect[j], aspect[j+1]);
  532.       SwapN(dest[j], dest[j+1]);
  533.       SwapR(&power[j], &power[j+1]);
  534.       j--;
  535.     }
  536.   }
  537.  
  538.   /* Now display each aspect line. */
  539.  
  540.   for (i = 0; i < occurcount; i++) {
  541.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  542.     j = source[i]; k = aspect[i]; l = dest[i];
  543.     PrintAspect(
  544.       j, SFromZ(planet[j]), (int)RSgn(ret[j]), k,
  545.       l, SFromZ(planet[l]), (int)RSgn(ret[l]), 'D');
  546.     m = grid->v[j][l];
  547.     AnsiColor(m < 0 ? kWhite : kLtGray);
  548.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  549.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  550.     AnsiColor(kDkGreen);
  551.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  552.     PrintInDay(j, k, l);
  553.   }
  554. }
  555.  
  556.  
  557. /* Given an arbitrary day, determine what aspects are made between this */
  558. /* transiting chart and the given natal chart, as specified with the -T */
  559. /* switch, and display the transits in order sorted by influence.       */
  560.  
  561. void ChartTransitInfluence(fProg)
  562. bool fProg;
  563. {
  564.   int source[MAXINDAY], aspect[MAXINDAY], dest[MAXINDAY];
  565.   real power[MAXINDAY];
  566.   byte ignore3[objMax];
  567.   char sz[cchSzDef];
  568.   int occurcount = 0, i, j, k, l, m;
  569.  
  570.   /* Cast the natal and transiting charts as with a relationship chart. */
  571.  
  572.   for (i = 1; i <= cSign; i++)
  573.     cp1.cusp[i] = house[i];
  574.   for (i = 1; i <= cObj; i++) {
  575.     cp1.obj[i] = planet[i];
  576.     cp1.dir[i] = ret[i];
  577.     ignore3[i] = ignore[i]; ignore[i] = ignore2[i];
  578.   }
  579.   ciCore = ciTwin;
  580.   if (us.fProgress = fProg) {
  581.     is.JDp = MdytszToJulian(MM, DD, YY, TT, SS, ZZ);
  582.     ciCore = ciMain;
  583.   }
  584.   CastChart(fTrue);
  585.   for (i = 1; i <= cSign; i++)
  586.     cp2.cusp[i] = house[i];
  587.   for (i = 1; i <= cObj; i++) {
  588.     cp2.obj[i] = planet[i];
  589.     cp2.dir[i] = ret[i];
  590.     ignore[i] = ignore3[i];
  591.   }
  592.  
  593.   /* Do a relationship aspect grid to get the transits. We have to make and */
  594.   /* restore three changes to get it right for this chart. (1) We make the  */
  595.   /* natal planets have zero velocity so applying vs. separating is only a  */
  596.   /* function of the transiter. (2) We force applying vs. separating orbs   */
  597.   /* regardless if -ga or -ma is in effect or not. (3) Finally we tweak the */
  598.   /* main restrictions to allow for transiting objects not restricted.      */
  599.  
  600.   for (i = 1; i <= cObj; i++) {
  601.     ret[i] = cp1.dir[i];
  602.     cp1.dir[i] = 0.0;
  603.     ignore3[i] = ignore[i];
  604.     ignore[i] = ignore[i] && ignore2[i];
  605.   }
  606.   i = us.fAppSep; us.fAppSep = fTrue;
  607.   FCreateGridRelation(fFalse);
  608.   us.fAppSep = i;
  609.   for (i = 1; i <= cObj; i++) {
  610.     cp1.dir[i] = ret[i];
  611.     ignore[i] = ignore3[i];
  612.   }
  613.  
  614.   /* Loop through the grid, and build up a list of the valid transits. */
  615.  
  616.   for (i = 1; i <= oNorm; i++) {
  617.     if (ignore2[i] || !FThing(i))
  618.       continue;
  619.     for (j = 1; j <= cObj; j++) {
  620.       if (ignore[j] || (k = grid->n[i][j]) == 0 || occurcount >= MAXINDAY)
  621.         continue;
  622.       source[occurcount] = i; aspect[occurcount] = k; dest[occurcount] = j;
  623.       l = grid->v[i][j];
  624.       power[occurcount] = rTransitInf[i]*
  625.         ((j <= oNorm ? rObjInf[j] : 2.0)/4.0)*rAspInf[k]*
  626.         (1.0-(real)abs(l)/60.0/GetOrb(i, j, k));
  627.       occurcount++;
  628.     }
  629.   }
  630.  
  631.   /* After all transits located, sort them by their total power. */
  632.  
  633.   for (i = 1; i < occurcount; i++) {
  634.     j = i-1;
  635.     while (j >= 0 && power[j] < power[j+1]) {
  636.       SwapN(source[j], source[j+1]);
  637.       SwapN(aspect[j], aspect[j+1]);
  638.       SwapN(dest[j], dest[j+1]);
  639.       SwapR(&power[j], &power[j+1]);
  640.       j--;
  641.     }
  642.   }
  643.  
  644.   /* Now loop through list and display each transit in effect at the time. */
  645.  
  646.   for (i = 0; i < occurcount; i++) {
  647.     k = aspect[i];
  648.     l = source[i];
  649.     sprintf(sz, "%3d: ", i+1); PrintSz(sz);
  650.     j = SFromZ(cp2.obj[l]);
  651.     PrintAspect(l, j, (int)RSgn(cp2.dir[l]), k,
  652.       dest[i], SFromZ(cp1.obj[dest[i]]), (int)RSgn(cp1.dir[dest[i]]),
  653.       (char)(fProg ? 'U' : 'T'));
  654.     m = grid->v[l][dest[i]];
  655.     AnsiColor(m < 0 ? kWhite : kLtGray);
  656.     sprintf(sz, "- %s%2d%c%02d'", m < 0 ? "app" : "sep",
  657.       abs(m)/60, chDeg1, abs(m)%60); PrintSz(sz);
  658.     AnsiColor(kDkGreen);
  659.     sprintf(sz, " - power:%6.2f", power[i]); PrintSz(sz);
  660.     if (k == aCon && l == dest[i]) {    /* Print a small "R" for returns. */
  661.       AnsiColor(kWhite);
  662.       PrintSz(" R");
  663.     }
  664.     PrintL();
  665. #ifdef INTERPRET
  666.     if (us.fInterpret)
  667.       InterpretTransit(l, k, dest[i]);
  668. #endif
  669.     AnsiColor(kDefault);
  670.   }
  671.   ciCore = ciMain;
  672.   CastChart(fTrue);
  673. }
  674.  
  675.  
  676. /* Given the zodiac location of a planet in the sky and its declination,   */
  677. /* and a location on the Earth, compute the azimuth and altitude of where  */
  678. /* on the local horizon sky the planet would appear to one at the given    */
  679. /* location. A reference MC position at Greenwich is also needed for this. */
  680.  
  681. void EclToHorizon(azi, alt, planet, planetalt, lon, lat, mc)
  682. real *azi, *alt, planet, planetalt, lon, lat, mc;
  683. {
  684.   real lonz, latz;
  685.  
  686.   lonz = RFromD(planet); latz = RFromD(planetalt);
  687.   EclToEqu(&lonz, &latz);
  688.   lonz = RFromD(Mod(DFromR(mc-lonz+lon)));
  689.   lonz = RFromD(Mod(DFromR(lonz-lon+rPiHalf)));
  690.   EquToLocal(&lonz, &latz, rPiHalf-lat);
  691.   *azi = rDegMax-DFromR(lonz); *alt = DFromR(latz);
  692. }
  693.  
  694.  
  695. /* Display a calendar for the given month in the chart, as specified with  */
  696. /* with the -K switch. When color is on, the title is white, weekends are  */
  697. /* highlighted in red, and the specific day in the chart is colored green. */
  698.  
  699. void ChartCalendarMonth()
  700. {
  701.   char sz[cchSzDef];
  702.   int i, j, k;
  703.  
  704.   AnsiColor(kWhite);
  705.   PrintTab(' ', 16-CchSz(szMonth[Mon]) >> 1);
  706.   sprintf(sz, "%s%5d\n", szMonth[Mon], Yea); PrintSz(sz);
  707.   for (i = 0; i < cWeek; i++) {
  708.     sprintf(sz, "%c%c%c", szDay[i][0], szDay[i][1], i < cWeek-1 ? ' ' : '\n');
  709.     PrintSz(sz);
  710.   }
  711.   j = DayOfWeek(Mon, 1, Yea);
  712.   AnsiColor(kDefault);
  713.   for (i = 0; i < j; i++) {
  714.     if (i == 0)
  715.       AnsiColor(kRainbowA[1]);
  716.     PrintSz("-- ");
  717.     if (i == 0)
  718.       AnsiColor(kDefault);
  719.   }
  720.   k = DayInMonth(Mon, Yea);
  721.   for (i = 1; i <= k; i = AddDay(Mon, i, Yea, 1)) {
  722.     if (i == (int)Day)
  723.       AnsiColor(kRainbowA[4]);
  724.     else if (j == 0 || j == cWeek-1)
  725.       AnsiColor(kRainbowA[1]);
  726.     sprintf(sz, "%2d", i); PrintSz(sz);
  727.     if (j == 0 || j == cWeek-1 || i == Day)
  728.       AnsiColor(kDefault);
  729.     if (j < cWeek-1) {
  730.       j++;
  731.       PrintCh(' ');
  732.     } else {
  733.       j = 0;
  734.       PrintL();
  735.     }
  736.   }
  737.   while (j > 0 && j < cWeek) {
  738.     if (j == cWeek-1)
  739.       AnsiColor(kRainbowA[1]);
  740.     j++;
  741.     sprintf(sz, "--%c", j < cWeek ? ' ' : '\n'); PrintSz(sz);
  742.   }
  743.   AnsiColor(kDefault);
  744. }
  745.  
  746.  
  747. /* Display a calendar for the entire year given in the chart, as specified */
  748. /* with the -Ky switch. This is just like twelve of the individual month   */
  749. /* calendars above displayed together, with same color highlights and all. */
  750.  
  751. void ChartCalendarYear()
  752. {
  753.   char sz[cchSzDef];
  754.   int r, w, c, m, d, dy, p[3], l[3], n[3];
  755.  
  756.   dy = DayOfWeek(1, 1, Yea);
  757.   for (r = 0; r < 4; r++) {     /* Loop over one set of three months */
  758.     AnsiColor(kWhite);
  759.     for (c = 0; c < 3; c++) {
  760.       m = r*3+c+1;
  761.       PrintTab(' ', 16-CchSz(szMonth[m]) >> 1);
  762.       sprintf(sz, "%s%5d", szMonth[m], Yea); PrintSz(sz);
  763.       if (c < 2)
  764.         PrintTab(' ', 20 + MONTHSPACE -
  765.           (16-CchSz(szMonth[m]) >> 1) - CchSz(szMonth[m]) - 5);
  766.     }
  767.     PrintL();
  768.     for (c = 0; c < 3; c++) {
  769.       for (d = 0; d < cWeek; d++) {
  770.         sprintf(sz, "%c%c%c", szDay[d][0], szDay[d][1],
  771.           d < cWeek-1 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  772.       }
  773.       if (c < 2)
  774.         PrintTab(' ', MONTHSPACE-1);
  775.       m = r*3+c+1;
  776.       p[c] = dy % cWeek;
  777.       l[c] = DayInMonth(m, Yea);
  778.       n[c] = 0;
  779.       dy += DaysInMonth(m, Yea);
  780.     }
  781.     for (w = 0; w < cWeek-1; w++) {    /* Loop over one set of week rows */
  782.       for (c = 0; c < 3; c++) {        /* Loop over one week in a month  */
  783.         m = r*3+c+1;
  784.         d = 0;
  785.         if (w == 0)
  786.           while (d < p[c]) {
  787.             if (d == 0)
  788.               AnsiColor(kRainbowA[1]);
  789.             PrintSz("-- ");
  790.             if (d == 0)
  791.               AnsiColor(kDefault);
  792.             d++;
  793.           }
  794.         AnsiColor(kDefault);
  795.         while (d < cWeek && n[c] < l[c]) {
  796.           n[c] = AddDay(m, n[c], Yea, 1);
  797.           if (n[c] == Day && m == Mon)
  798.             AnsiColor(kRainbowA[4]);
  799.           else if (d == 0 || d == cWeek-1)
  800.             AnsiColor(kRainbowA[1]);
  801.           sprintf(sz, "%2d%c", n[c], d < cWeek-1 || c < 2 ? ' ' : '\n');
  802.           PrintSz(sz);
  803.           if (d == 0 || d == cWeek-1 || (n[c] == Day && m == Mon))
  804.             AnsiColor(kDefault);
  805.           d++;
  806.         }
  807.         while (d < cWeek) {
  808.           if (d == 0 || d == cWeek-1)
  809.             AnsiColor(kRainbowA[1]);
  810.           sprintf(sz, "--%c", d < cWeek-1 || c < 2 ? ' ' : '\n'); PrintSz(sz);
  811.           if (d == 0)
  812.             AnsiColor(kDefault);
  813.           d++;
  814.         }
  815.         if (c < 2)
  816.           PrintTab(' ', MONTHSPACE-1);
  817.       }
  818.     }
  819.     if (r < 3)
  820.       PrintL();
  821.   }
  822.   AnsiColor(kDefault);
  823. }
  824.  
  825.  
  826. /* Display either a biorhythm chart or the time difference in various units */
  827. /* between two charts, i.e. two types of relationship "charts" that aren't  */
  828. /* related in any way to planetary positions, as specified by either the    */
  829. /* -rb or -rd switches, respectively.                                       */
  830.  
  831. void DisplayRelation()
  832. {
  833.   char sz[cchSzDef];
  834.   int i;
  835. #ifdef BIORHYTHM
  836.   int j;
  837.   real k, l;
  838. #endif
  839.  
  840.   /* If we are calculating the difference between two dates, then display */
  841.   /* the value and return, as with the -rd switch.                        */
  842.  
  843.   if (us.nRel == rcDifference) {
  844.     PrintSz("Differences between the dates in the two charts:\n");
  845.     for (i = 1; i <= 7; i++) {
  846.       AnsiColor(kRainbowA[i]);
  847.       switch (i) {
  848.       case 1: sprintf(sz, "Years  : %.0f", is.JD/365.25);      break;
  849.       case 2: sprintf(sz, "Months : %.0f", is.JD/(365.25/12)); break;
  850.       case 3: sprintf(sz, "Weeks  : %.0f", is.JD/7.0);         break;
  851.       case 4: sprintf(sz, "Days   : %.0f", is.JD);             break;
  852.       case 5: sprintf(sz, "Hours  : %.0f", is.JD*24.0);        break;
  853.       case 6: sprintf(sz, "Minutes: %.0f", is.JD*24.0*60.0);   break;
  854.       case 7: sprintf(sz, "Seconds: %.0f", is.JD*24.0*3600.0); break;
  855.       }
  856.       PrintSz(sz);
  857.       PrintL();
  858.     }
  859.     AnsiColor(kDefault);
  860.     return;
  861.   }
  862.  
  863. #ifdef BIORHYTHM
  864.   /* If we are doing a biorhythm (-rb switch), then we'll calculate it for */
  865.   /* someone born on the older date, at the time of the younger date. Loop */
  866.   /* through the week preceeding and following the date in question.       */
  867.  
  868.   is.JD = RFloor(is.JD + rRound);
  869.   for (is.JD -= 7.0, i = -7; i <= 7; i++, is.JD += 1.0) {
  870.     if (i == 0)
  871.       AnsiColor(kWhite);
  872.     else if (i == 1)
  873.       AnsiColor(kDefault);
  874.     sprintf(sz, "T%c%d Day%c:",
  875.       i < 0 ? '-' : '+', abs(i), abs(i) != 1 ? 's' : ' '); PrintSz(sz);
  876.     for (j = 1; j <= 3; j++) {
  877.       PrintCh(' ');
  878.       switch (j) {
  879.       case 1: k = brPhy; AnsiColor(kRed);   PrintSz("Physical");     break;
  880.       case 2: k = brEmo; AnsiColor(kBlue);  PrintSz("Emotional");    break;
  881.       case 3: k = brInt; AnsiColor(kGreen); PrintSz("Intellectual"); break;
  882.       }
  883.       AnsiColor(i ? kDefault : kWhite);
  884.  
  885.       /* The biorhythm calculation is below. */
  886.  
  887.       l = RBiorhythm(is.JD, k);
  888.       sprintf(sz, " at %c%3.0f%%", l < 0.0 ? '-' : '+', RAbs(l)); PrintSz(sz);
  889.  
  890.       /* Print smiley face, medium face, or sad face based on current cycle. */
  891.  
  892.       AnsiColor(kPurple);
  893.       sprintf(sz, " :%c", l > 50.0 ? ')' : (l < -50.0 ? '(' : '|'));
  894.       PrintSz(sz);
  895.       AnsiColor(i ? kDefault : kWhite);
  896.       if (j < 3)
  897.         PrintCh(',');
  898.     }
  899.     PrintL();
  900.   }
  901. #endif /* BIORHYTHM */
  902. }
  903.  
  904. /* charts2.c */
  905.